package cn.com.anysdk.ocr.factory;

import cn.com.anysdk.ocr.exception.OcrException;
import cn.com.anysdk.ocr.monitor.OcrMonitorManager;
import cn.com.anysdk.ocr.monitor.OcrOperationContext;
import cn.com.anysdk.ocr.service.IOcrService;
import lombok.extern.slf4j.Slf4j;

import java.io.File;
import java.io.InputStream;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.List;

/**
 * OCR 服务代理工厂
 * 用于创建带有异常处理和监控功能的 OCR 服务代理
 */
@Slf4j
public class OcrServiceProxyFactory {
    /**
     * 创建 OCR 服务代理
     * @param service 原始 OCR 服务
     * @return 代理后的 OCR 服务
     */
    public static IOcrService createProxy(IOcrService service) {
        return (IOcrService) Proxy.newProxyInstance(
                service.getClass().getClassLoader(),
                new Class<?>[]{IOcrService.class},
                new OcrServiceInvocationHandler(service)
        );
    }

    private static class OcrServiceInvocationHandler implements InvocationHandler {
        private final IOcrService target;

        public OcrServiceInvocationHandler(IOcrService target) {
            this.target = target;
        }

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            OcrOperationContext context = OcrOperationContext.builder()
                    .provider(getProvider(target.getClass().getSimpleName()))
                    .operationType(getOperationType(method.getName()))
                    .build();

            try {
                Object result = method.invoke(target, args);
                return result;
            } catch (Exception e) {
                Throwable cause = e.getCause();
                if (cause instanceof OcrException) {
                    OcrMonitorManager.getInstance().notifyListeners((OcrException) cause, context);
                    throw cause;
                } else {
                    String errorMessage = String.format("OCR %s failed: %s",
                            context.getOperationType().name().toLowerCase(), e.getMessage());
                    OcrException ocrException = new OcrException(errorMessage, e);
                    OcrMonitorManager.getInstance().notifyListeners(ocrException, context);
                    throw ocrException;
                }
            }
        }

        private OcrOperationContext.Provider getProvider(String className) {
            if (className.contains("Aliyun")) {
                return OcrOperationContext.Provider.ALIYUN;
            } else if (className.contains("Tencent")) {
                return OcrOperationContext.Provider.TENCENT;
            } else if (className.contains("Baidu")) {
                return OcrOperationContext.Provider.BAIDU;
            } else {
                return OcrOperationContext.Provider.LOCAL;
            }
        }

        private OcrOperationContext.OperationType getOperationType(String methodName) {
            if (methodName.startsWith("recognize")) {
                if (methodName.contains("Batch")) {
                    return OcrOperationContext.OperationType.BATCH_RECOGNIZE;
                } else {
                    return OcrOperationContext.OperationType.RECOGNIZE;
                }
            }
            return null;
        }
    }
}